package pl.edu.agh.iosr.gamblingzone.utils;

import java.util.Hashtable;

import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.jboss.seam.annotations.Name;

import pl.edu.agh.iosr.gamblingzone.dao.AbstractEventDAO;
import pl.edu.agh.iosr.gamblingzone.dao.BetDAO;
import pl.edu.agh.iosr.gamblingzone.dao.BettingSlipDAO;
import pl.edu.agh.iosr.gamblingzone.dao.DisciplineDAO;
import pl.edu.agh.iosr.gamblingzone.dao.GenericDAO;
import pl.edu.agh.iosr.gamblingzone.dao.GroupDAO;
import pl.edu.agh.iosr.gamblingzone.dao.MoneyVoucherDAO;
import pl.edu.agh.iosr.gamblingzone.dao.MoneyVoucherRequestDAO;
import pl.edu.agh.iosr.gamblingzone.dao.ParticipantDAO;
import pl.edu.agh.iosr.gamblingzone.dao.QuoteDAO;
import pl.edu.agh.iosr.gamblingzone.dao.UserDAO;
import pl.edu.agh.iosr.gamblingzone.dao.hibernate.AbstractEventDAOBean;
import pl.edu.agh.iosr.gamblingzone.dao.hibernate.BetDAOBean;
import pl.edu.agh.iosr.gamblingzone.dao.hibernate.BettingSlipDAOBean;
import pl.edu.agh.iosr.gamblingzone.dao.hibernate.DisciplineDAOBean;
import pl.edu.agh.iosr.gamblingzone.dao.hibernate.GroupDAOBean;
import pl.edu.agh.iosr.gamblingzone.dao.hibernate.MoneyVoucherDAOBean;
import pl.edu.agh.iosr.gamblingzone.dao.hibernate.MoneyVoucherRequestDAOBean;
import pl.edu.agh.iosr.gamblingzone.dao.hibernate.ParticipantDAOBean;
import pl.edu.agh.iosr.gamblingzone.dao.hibernate.QuoteDAOBean;
import pl.edu.agh.iosr.gamblingzone.dao.hibernate.UserDAOBean;

/**
 * The Class DAOFactoryBean.
 * 
 * @param <T>  */
@Stateless
@Name("dao2")
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public class HibernateDAOFactoryBean implements DAOFactory {
	
	/** The entity manager. */
	@PersistenceContext
	EntityManager entityManager;

	/* (non-Javadoc)
	 * @see pl.edu.agh.iosr.gamblingzone.utils.DAOFactory#getBetDAO()
	 */
	@SuppressWarnings("unchecked")
	public BetDAO getBetDAO() {
		return (BetDAO)instantionateDAO(BetDAOBean.class);
	}

	/* (non-Javadoc)
	 * @see pl.edu.agh.iosr.gamblingzone.utils.DAOFactory#getDisciplineDAO()
	 */
	@SuppressWarnings("unchecked")
	public DisciplineDAO getDisciplineDAO() {
		return (DisciplineDAO)instantionateDAO(DisciplineDAOBean.class);
	}

	/* (non-Javadoc)
	 * @see pl.edu.agh.iosr.gamblingzone.utils.DAOFactory#getEventDAO()
	 */
	@SuppressWarnings("unchecked")
	public AbstractEventDAO getEventDAO() {
		return (AbstractEventDAO)instantionateDAO(AbstractEventDAOBean.class);
	}

	/* (non-Javadoc)
	 * @see pl.edu.agh.iosr.gamblingzone.utils.DAOFactory#getGroupDAO()
	 */
	@SuppressWarnings("unchecked")
	public GroupDAO getGroupDAO() {
		return (GroupDAO)instantionateDAO(GroupDAOBean.class);
	}

	/* (non-Javadoc)
	 * @see pl.edu.agh.iosr.gamblingzone.utils.DAOFactory#getParticipantDAO()
	 */
	@SuppressWarnings("unchecked")
	public ParticipantDAO getParticipantDAO() {
		return (ParticipantDAO)instantionateDAO(ParticipantDAOBean.class);
	}

	/* (non-Javadoc)
	 * @see pl.edu.agh.iosr.gamblingzone.utils.DAOFactory#getQuoteDAO()
	 */
	@SuppressWarnings("unchecked")
	public QuoteDAO getQuoteDAO() {
		return (QuoteDAO)instantionateDAO(QuoteDAOBean.class);
	}

	/* (non-Javadoc)
	 * @see pl.edu.agh.iosr.gamblingzone.utils.DAOFactory#getSlipDAO()
	 */
	@SuppressWarnings("unchecked")
	public BettingSlipDAO getSlipDAO() {
		return (BettingSlipDAO)instantionateDAO(BettingSlipDAOBean.class);
	}

	/* (non-Javadoc)
	 * @see pl.edu.agh.iosr.gamblingzone.utils.DAOFactory#getUserDAO()
	 */
	@SuppressWarnings("unchecked")
	public UserDAO getUserDAO() {
		return (UserDAO)instantionateDAO(UserDAOBean.class);
	}

	/* (non-Javadoc)
	 * @see pl.edu.agh.iosr.gamblingzone.utils.DAOFactory#getVoucherDAO()
	 */
	@SuppressWarnings("unchecked")
	public MoneyVoucherDAO getVoucherDAO() {
		return (MoneyVoucherDAO)instantionateDAO(MoneyVoucherDAOBean.class);
	}

	/* (non-Javadoc)
	 * @see pl.edu.agh.iosr.gamblingzone.utils.DAOFactory#getVoucherRequestDAO()
	 */
	@SuppressWarnings("unchecked")
	public MoneyVoucherRequestDAO getVoucherRequestDAO() {
		return (MoneyVoucherRequestDAO)instantionateDAO(MoneyVoucherRequestDAOBean.class);
	}
	
	/**
	 * Instantionate dao.
	 * 
	 * @param classDAO the class dao
	 * 
	 * @return the generic da o<?, long>
	 */
	@SuppressWarnings({"unchecked" })
	private GenericDAO<?, Long> instantionateDAO(Class classDAO) {	
		GenericDAO<?, Long> dao = null;
		
		System.out.println("=======================================================");
		
		// check whether entity manager is properly injected
		if (entityManager == null) {
			// most probably we're in embedded environment
			Hashtable props =  new Hashtable();
			props.put("java.naming.factory.initial", "org.jnp.interfaces.LocalOnlyContextFactory");
			props.put("java.naming.factory.url.pkgs", "org.jboss.naming:org.jnp.interfaces");
			InitialContext ctx;
			try {
				ctx = new InitialContext(props);
				entityManager = (EntityManager) ctx.lookup("java:/EntityManagers/gamblingzoneDatabase");
			} catch (NamingException e) {
				throw new RuntimeException("couldn't instantiate entity managager: ");
			}
			
		}

		try {
			dao = (GenericDAO<?, Long>)classDAO.newInstance();
			dao.setEntityManager(entityManager);
		} catch (InstantiationException e) {
			throw new RuntimeException("couldn't instantiate DAO: "+classDAO, e);
		} catch (IllegalAccessException e) {
			throw new RuntimeException("couldn't instantiate DAO - illegal access:  "+classDAO, e);
		}
	
		return dao;
	}

	public EntityManager getEntityManager() {
		return entityManager;
	}

	public void setEntityManager(EntityManager entityManager) {
		this.entityManager = entityManager;
	}

}
